"""
并发编程
    ~ 多线程：交互性较好的用户界面 / 任务委派 / 非计算机密集型任务
        - CPython / PyPy - 有全局解释器锁 - 底层内存管理的C代码并非线程安全 - 无法使用多核特性
        - Jython / IronPython / Stackless Python - 没有全局GIL
    ~ 多进程：Python的多进程和多线程代码结构上非常类似，但是由于进程间的内存是隔离的，
    所以进程间通信比线程间通信要麻烦得多，适合计算密集型任务
    ~ 异步编程：协作式多并发，多路I/O复用、异步I/O适合I/O密集型任务
问题1：线程和进程的区别？
问题2：进程间通信的方式？
问题3：什么时候使用多线程？什么时候使用多进程？
临界资源：被多个线程竞争的资源称为临界资源（有竞争风险的资源）
如果需要对临界资源进行保护，做到访问互斥，需要对资源加锁进行保护
有5个线程存钱，每次存入10-20元；有10个线程取钱每次取出10-30元；
存钱取钱的操作必须互斥（保护银行账户数据不出错），如果余额不足则阻塞取钱操作，
被阻塞的线程需要释放锁让存钱线程有机会把钱存入进来；存钱线程在存入钱以后，
需要通知被阻塞的取钱线程，可以尝试重新做取钱的操作 - 线程调度
"""
from concurrent.futures import ThreadPoolExecutor
from threading import RLock, Condition
from time import sleep


class Account:

    def __init__(self):
        self.balance = 0.0
        # Reentrant Lock - 重入锁
        self.lock = RLock()
        self.condition = Condition(self.lock)

    def deposit(self, money):
        with self.lock:
            new_balance = self.balance + money
            sleep(0.001)
            self.balance = new_balance


def main():
    account = Account()
    futures = []
    with ThreadPoolExecutor(max_workers=16) as pool:
        for _ in range(100):
            future = pool.submit(account.deposit, 1)
            futures.append(future)
    for future in futures:
        while not future.done():
            pass
    print(account.balance)


if __name__ == '__main__':
    main()
